import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:path_provider/path_provider.dart';
import 'package:uuid/uuid.dart';

/// @desc  音频播放器    原有的audioplayers插件没有速度和音高控制，所以增加使用just_audio
/// @author  hxg
///@date   2025-05-23
/**
 *
    // 初始化播放器（建议在应用启动时执行）
    await AudioManager().init();
    // 加载并播放音频文件
    await AudioManager().loadAudio('https://example.com/audio.mp3');
    await AudioManager().play();

    // 播放音频并设置回调
    AudioManager().playAudio(
    'https://example.com/audio.mp3',
    onDuration: (duration) => print('音频总时长: $duration'),
    onPosition: (position) => print('当前播放位置: $position'),
    onPlayError: (error) => print('播放错误: $error'),
    onComplete: () => print('播放完成'),
    );

    // 获取当前播放音频信息
    AudioInfo audioInfo = AudioManager().getCurrentAudio();
    print('当前播放: ${audioInfo.title} - ${audioInfo.artist}');


    // 获取当前播放音频信息
    AudioInfo? audioInfo = AudioManager().getCurrentAudio();
    if (audioInfo != null) {
    print('当前播放: ${audioInfo.title} ${audioInfo.artist != null ? "- ${audioInfo.artist}" : ""}');
    print('时长: ${audioInfo.duration}');
    }

    // 使用流来监听音频信息变化
    AudioManager().audioInfoStream.listen((audioInfo) {
    if (audioInfo != null) {
    print('音频已更改: ${audioInfo.title}');
    } else {
    print('没有正在播放的音频');
    }
    });
    // 可以在加载音频时提供完整的元数据：
    await AudioManager().loadAudio(
    'https://example.com/audio.mp3',
    title: '歌曲标题',
    artist: '艺术家',
    album: '专辑名称',
    artworkUrl: 'https://example.com/cover.jpg',
    );


    // 方式1：使用回调
    AudioManager().onPlaybackStateChanged = (state) {
    print('播放状态: ${state.state}');
    print('当前音频: ${state.audioInfo?.title}');
    print('播放位置: ${state.position}');
    print('总时长: ${state.duration}');
    if (state.error != null) {
    print('错误信息: ${state.error}');
    }
    };

    // 方式2：使用流
    AudioManager().playbackStateStream.listen((state) {
    print('播放状态: ${state.state}');
    print('当前音频: ${state.audioInfo?.title}');
    print('播放位置: ${state.position}');
    print('总时长: ${state.duration}');
    if (state.error != null) {
    print('错误信息: ${state.error}');
    }
    });

    // 获取当前状态
    PlaybackStateInfo currentState = AudioManager().playbackState;
    print('当前状态: ${currentState.state}');

 */

/// 播放状态枚举
enum PlaybackState {
  /// 未初始化
  uninitialized,
  /// 已加载但未播放
  loaded,
  /// 正在播放
  playing,
  /// 已暂停
  paused,
  /// 已停止
  stopped,
  /// 播放完成
  completed,
  /// 发生错误
  error,
  /// 正在缓冲
  buffering
}

/// 播放状态信息类
class PlaybackStateInfo {
  /// 当前播放状态
  final PlaybackState state;
  /// 当前播放的音频信息
  final AudioInfo? audioInfo;
  /// 错误信息（如果有）
  final String? error;
  /// 是否正在缓冲
  final bool isBuffering;
  /// 当前播放位置
  final Duration position;
  /// 总时长
  final Duration duration;

  PlaybackStateInfo({
    required this.state,
    this.audioInfo,
    this.error,
    this.isBuffering = false,
    this.position = Duration.zero,
    this.duration = Duration.zero,
  });

  /// 复制并更新状态信息
  PlaybackStateInfo copyWith({
    PlaybackState? state,
    AudioInfo? audioInfo,
    String? error,
    bool? isBuffering,
    Duration? position,
    Duration? duration,
  }) {
    return PlaybackStateInfo(
      state: state ?? this.state,
      audioInfo: audioInfo ?? this.audioInfo,
      error: error ?? this.error,
      isBuffering: isBuffering ?? this.isBuffering,
      position: position ?? this.position,
      duration: duration ?? this.duration,
    );
  }
}

/// 音频信息类，存储音频相关数据
class AudioInfo {
  /// 音频唯一标识符
  final String id;

  /// 音频标题
  final String title;

  /// 音频艺术家
  final String? artist;

  /// 音频专辑
  final String? album;

  /// 音频时长
  final Duration? duration;

  /// 音频源URL或文件路径
  final String source;

  /// 音频是否是本地文件
  final bool isLocalFile;

  /// 音频封面图片URL
  final String? artworkUrl;

  /// 附加数据
  final Map<String, dynamic>? extras;

  /// 构造函数
  AudioInfo({
    String? id,
    required this.title,
    this.artist,
    this.album,
    this.duration,
    required this.source,
    required this.isLocalFile,
    this.artworkUrl,
    this.extras,
  }) : id = id ?? const Uuid().v4();

  /// 从文件路径创建音频信息
  factory AudioInfo.fromFilePath(String filePath) {
    final filename = filePath.split('/').last.split('\\').last;
    final title = filename.contains('.')
        ? filename.substring(0, filename.lastIndexOf('.'))
        : filename;

    return AudioInfo(
      title: title,
      source: filePath,
      isLocalFile: true,
    );
  }

  /// 从URL创建音频信息
  factory AudioInfo.fromUrl(String url, {String? title, String? artist}) {
    final defaultTitle = url.split('/').last;
    return AudioInfo(
      title: title ?? defaultTitle,
      artist: artist,
      source: url,
      isLocalFile: false,
    );
  }

  /// 复制并更新音频信息
  AudioInfo copyWith({
    String? id,
    String? title,
    String? artist,
    String? album,
    Duration? duration,
    String? source,
    bool? isLocalFile,
    String? artworkUrl,
    Map<String, dynamic>? extras,
  }) {
    return AudioInfo(
      id: id ?? this.id,
      title: title ?? this.title,
      artist: artist ?? this.artist,
      album: album ?? this.album,
      duration: duration ?? this.duration,
      source: source ?? this.source,
      isLocalFile: isLocalFile ?? this.isLocalFile,
      artworkUrl: artworkUrl ?? this.artworkUrl,
      extras: extras ?? this.extras,
    );
  }

  @override
  String toString() => '${artist != null ? "$artist - " : ""}$title';
}

/// 音频播放管理器，处理前台音频播放，集成just_audio
/// A manager for audio playback that handles foreground playback
/// using just_audio.
class AudioManager {
  // 单例模式实现
  static final AudioManager _instance = AudioManager._internal();
  factory AudioManager() => _instance;
  AudioManager._internal();

  // 音频播放器
  late AudioPlayer _player;

  // 当前播放的音频信息
  AudioInfo? _currentAudio;

  // 添加播放状态相关属性
  PlaybackStateInfo _playbackState = PlaybackStateInfo(state: PlaybackState.uninitialized);
  PlaybackStateInfo get playbackState => _playbackState;
  
  // 添加播放状态流控制器
  final _playbackStateStreamController = StreamController<PlaybackStateInfo>.broadcast();
  Stream<PlaybackStateInfo> get playbackStateStream => _playbackStateStreamController.stream;

  // 播放状态变化回调
  Function(PlaybackStateInfo state)? onPlaybackStateChanged;

  // 声明为可空的 late 变量
  late StreamController<bool> _playingStreamController;
  late StreamController<Duration> _progressStreamController;
  late StreamController<Duration> _totalDurationStreamController;
  late StreamController<bool> _bufferingStreamController;
  late StreamController<String> _errorStreamController;
  late StreamController<AudioInfo?> _audioInfoStreamController;

  // 初始化时创建新的 StreamController
  void _initializeStreamControllers() {
    _playingStreamController = StreamController<bool>.broadcast();
    _progressStreamController = StreamController<Duration>.broadcast();
    _totalDurationStreamController = StreamController<Duration>.broadcast();
    _bufferingStreamController = StreamController<bool>.broadcast();
    _errorStreamController = StreamController<String>.broadcast();
    _audioInfoStreamController = StreamController<AudioInfo?>.broadcast();
  }

  // 流对外暴露
  Stream<bool> get playingStream => _playingStreamController.stream;
  Stream<Duration> get progressStream => _progressStreamController.stream;
  Stream<Duration> get totalDurationStream =>
      _totalDurationStreamController.stream;
  Stream<bool> get bufferingStream => _bufferingStreamController.stream;
  Stream<String> get errorStream => _errorStreamController.stream;
  Stream<AudioInfo?> get audioInfoStream => _audioInfoStreamController.stream;

  // 当前状态属性
  bool _initialized = false;
  bool get isInitialized => _initialized;
  bool get isPlaying => _initialized ? _player.playing : false;
  Duration get currentPosition =>
      _initialized ? _player.position : Duration.zero;
  Duration get totalDuration =>
      _initialized ? (_player.duration ?? Duration.zero) : Duration.zero;
  double get volume => _initialized ? _player.volume : 1.0;
  double get speed => _initialized ? _player.speed : 1.0;
  bool get isBuffering =>
      _initialized && _player.processingState == ProcessingState.buffering;

  // 回调函数定义
  Function(Duration duration)? onDurationChanged;
  Function(Duration position)? onPositionChanged;
  Function(String error)? onError;
  Function()? onCompleted;
  Function(AudioInfo audioInfo)? onAudioChanged;

  // 添加音调控制相关属性
  double _pitch = 1.0;
  double get pitch => _pitch;

  /// 初始化音频管理器，在使用其他方法前必须先调用此方法
  /// Initialize the AudioManager. Must be called before using any other methods.
  Future<void> init() async {
    if (_initialized) return;

    try {
      _initializeStreamControllers();
      // 初始化播放器
      _player = AudioPlayer();

      // 设置事件监听
      _player.playerStateStream.listen((state) {
        _playingStreamController.add(state.playing);

        // 更新播放状态
        PlaybackState newState;
        if (state.processingState == ProcessingState.completed) {
          newState = PlaybackState.completed;
        } else if (state.processingState == ProcessingState.buffering) {
          newState = PlaybackState.buffering;
        } else if (state.playing) {
          newState = PlaybackState.playing;
        } else {
          newState = PlaybackState.paused;
        }

        _updatePlaybackState(
          state: newState,
          isBuffering: state.processingState == ProcessingState.buffering,
        );

        // 播放完成时触发回调
        if (state.processingState == ProcessingState.completed && onCompleted != null) {
          onCompleted!();
        }
      });

      _player.positionStream.listen((position) {
        _progressStreamController.add(position);

        // 更新播放状态中的位置信息
        _updatePlaybackState(position: position);

        // 触发进度变化回调
        if (onPositionChanged != null) {
          onPositionChanged!(position);
        }
      });

      _player.durationStream.listen((duration) {
        if (duration != null) {
          _totalDurationStreamController.add(duration);

          // 更新当前音频信息的时长
          if (_currentAudio != null) {
            _currentAudio = _currentAudio!.copyWith(duration: duration);
            _audioInfoStreamController.add(_currentAudio);
            
            // 更新播放状态中的时长信息
            _updatePlaybackState(duration: duration);
          }

          // 触发总时长变化回调
          if (onDurationChanged != null) {
            onDurationChanged!(duration);
          }
        }
      });

      _player.processingStateStream.listen((state) {
        _bufferingStreamController.add(state == ProcessingState.buffering);
        
        // 更新播放状态中的缓冲状态
        _updatePlaybackState(
          isBuffering: state == ProcessingState.buffering,
          state: state == ProcessingState.buffering ? PlaybackState.buffering : _playbackState.state,
        );
      });

      // 添加错误监听
      _player.playbackEventStream.listen((event) {},
          onError: (Object e, StackTrace st) {
        final errorMessage = e is PlayerException
            ? '播放器错误: ${e.code}, ${e.message}'
            : '播放错误: $e';

        _errorStreamController.add(errorMessage);

        // 更新播放状态为错误状态
        _updatePlaybackState(
          state: PlaybackState.error,
          error: errorMessage,
        );

        // 触发错误回调
        if (onError != null) {
          onError!(errorMessage);
        }
      });

      _initialized = true;
      debugPrint('AudioManager 初始化成功');
    } catch (e) {
      debugPrint('AudioManager 初始化失败: $e');
      rethrow;
    }
  }

  /// 更新播放状态
  void _updatePlaybackState({
    PlaybackState? state,
    AudioInfo? audioInfo,
    String? error,
    bool? isBuffering,
    Duration? position,
    Duration? duration,
  }) {
    _playbackState = _playbackState.copyWith(
      state: state ?? _playbackState.state,
      audioInfo: audioInfo ?? _playbackState.audioInfo,
      error: error ?? _playbackState.error,
      isBuffering: isBuffering ?? _playbackState.isBuffering,
      position: position ?? _playbackState.position,
      duration: duration ?? _playbackState.duration,
    );

    // 发送状态更新到流
    _playbackStateStreamController.add(_playbackState);

    // 触发状态变化回调
    if (onPlaybackStateChanged != null) {
      onPlaybackStateChanged!(_playbackState);
    }
  }

  /// 加载音频（支持网络链接或本地文件路径）
  /// Load audio from a URL (either network or local file path)
  Future<void> loadAudio(
      String url, {
        Map<String, String>? headers,
        String? title,
        String? artist,
        String? album,
        String? artworkUrl,
        Map<String, dynamic>? extras,
      }) async {
    if (!_initialized) await init();

    try {
      // 更新状态为加载中
      _updatePlaybackState(state: PlaybackState.loaded);

      // 判断是本地文件还是网络链接
      final isLocalFile = url.startsWith('/') ||
          url.startsWith('file://') ||
          (Platform.isWindows && url.contains(':\\'));

      // 创建音频信息
      final audioInfo = isLocalFile
          ? AudioInfo.fromFilePath(url).copyWith(
        title: title,
        artist: artist,
        album: album,
        artworkUrl: artworkUrl,
        extras: extras,
      )
          : AudioInfo.fromUrl(
        url,
        title: title,
        artist: artist,
      ).copyWith(
        album: album,
        artworkUrl: artworkUrl,
        extras: extras,
      );

      // 加载音频源
      if (isLocalFile) {
        String filePath = url;
        if (url.startsWith('file://')) {
          filePath = url.substring(7);
        }
        await _player.setFilePath(filePath);
      } else {
        await _player.setUrl(url, headers: headers);
      }
      // 应用当前音调设置
      await _player.setPitch(_pitch);

      // 更新当前音频信息
      _currentAudio = audioInfo.copyWith(duration: _player.duration);
      _audioInfoStreamController.add(_currentAudio);

      // 更新播放状态
      _updatePlaybackState(
        audioInfo: _currentAudio,
        duration: _player.duration,
      );

      // 触发音频变化回调
      if (onAudioChanged != null && _currentAudio != null) {
        onAudioChanged!(_currentAudio!);
      }

      debugPrint('加载音频成功: ${audioInfo.title}');
    } catch (e) {
      final errorMessage = '加载音频失败: $e';
      debugPrint(errorMessage);

      // 更新状态为错误
      _updatePlaybackState(
        state: PlaybackState.error,
        error: errorMessage,
      );

      // 发送错误到流和回调
      _errorStreamController.add(errorMessage);
      if (onError != null) {
        onError!(errorMessage);
      }

      rethrow;
    }
  }

  /// 从本地资源加载音频
  /// Load audio from a local asset
  Future<void> loadAsset(
      String assetPath, {
        String? title,
        String? artist,
        String? album,
        String? artworkUrl,
        Map<String, dynamic>? extras,
      }) async {
    if (!_initialized) await init();

    try {
      // 创建音频信息
      final filename = assetPath.split('/').last;
      final defaultTitle = filename.contains('.')
          ? filename.substring(0, filename.lastIndexOf('.'))
          : filename;

      final audioInfo = AudioInfo(
        title: title ?? defaultTitle,
        artist: artist,
        album: album,
        source: assetPath,
        isLocalFile: true,
        artworkUrl: artworkUrl,
        extras: extras,
      );

      await _player.setAsset(assetPath);

      // 更新当前音频信息
      _currentAudio = audioInfo.copyWith(duration: _player.duration);
      _audioInfoStreamController.add(_currentAudio);

      // 更新播放状态
      _updatePlaybackState(
        audioInfo: _currentAudio,
        duration: _player.duration,
      );

      // 触发音频变化回调
      if (onAudioChanged != null && _currentAudio != null) {
        onAudioChanged!(_currentAudio!);
      }

      debugPrint('加载资源音频成功: ${audioInfo.title}');
    } catch (e) {
      final errorMessage = '加载资源音频失败: $e';
      debugPrint(errorMessage);

      // 更新状态为错误
      _updatePlaybackState(
        state: PlaybackState.error,
        error: errorMessage,
      );

      // 发送错误到流和回调
      _errorStreamController.add(errorMessage);
      if (onError != null) {
        onError!(errorMessage);
      }

      rethrow;
    }
  }

  /// 获取当前播放的音频信息
  /// Get information about the currently playing audio
  AudioInfo? getCurrentAudio() {
    return _currentAudio;
  }

  /// 开始或恢复播放
  /// Start or resume playback
  Future<void> play() async {
    if (!_initialized) await init();
    await _player.play();
    _updatePlaybackState(state: PlaybackState.playing);
  }

  /// 暂停播放
  /// Pause playback
  Future<void> pause() async {
    if (!_initialized) return;
    await _player.pause();
    _updatePlaybackState(state: PlaybackState.paused);
  }

  /// 停止播放并将位置重置到开始
  /// Stop playback and reset position to the beginning
  Future<void> stop() async {
    if (!_initialized) return;
    await _player.stop();
    await _player.seek(Duration.zero);
    _updatePlaybackState(
      state: PlaybackState.stopped,
      position: Duration.zero,
    );
  }

  /// 跳转到指定位置
  /// Seek to a specific position
  Future<void> seek(Duration position) async {
    if (!_initialized) return;
    await _player.seek(position);
  }

  /// 设置音量（-3到3）
  /// Set the volume (0.0 to 1.0)
  Future<void> setVolume(double volume) async {
    if (!_initialized) return;
    await _player.setVolume(volume.clamp(-3,3));
  }

  /// 设置播放速度
  /// Set the playback speed
  Future<void> setSpeed(double speed) async {
    if (!_initialized) return;
    await _player.setSpeed(speed.clamp(0.7, 1.5));
  }

  /// 在播放和暂停状态之间切换
  /// Toggle between playing and paused states
  Future<void> togglePlay() async {
    if (!_initialized) await init();

    if (_player.playing) {
      await pause();
    } else {
      await play();
    }
  }

  /// 加载并播放音频，同时设置回调
  /// Load and play audio with callbacks
  Future<void> playAudio(
      String url, {
        Map<String, String>? headers,
        String? title,
        String? artist,
        String? album,
        String? artworkUrl,
        Map<String, dynamic>? extras,
        Function(Duration duration)? onDuration,
        Function(Duration position)? onPosition,
        Function(String error)? onPlayError,
        Function()? onComplete,
        Function(AudioInfo audioInfo)? onAudioLoaded,
      }) async {
    try {
      // 设置回调
      this.onDurationChanged = onDuration;
      this.onPositionChanged = onPosition;
      this.onError = onPlayError;
      this.onCompleted = onComplete;
      this.onAudioChanged = onAudioLoaded;

      // 加载并播放
      await loadAudio(
        url,
        headers: headers,
        title: title,
        artist: artist,
        album: album,
        artworkUrl: artworkUrl,
        extras: extras,
      );
      await play();

      // 手动触发一次音频加载回调
      if (onAudioLoaded != null && _currentAudio != null) {
        onAudioLoaded(_currentAudio!);
      }
    } catch (e) {
      final errorMessage = '播放音频失败: $e';
      debugPrint(errorMessage);

      if (onPlayError != null) {
        onPlayError(errorMessage);
      }
    }
  }

  /// 下载音频从网络链接到本地存储
  /// Download audio from a URL to local storage
  Future<String> downloadAudio(String url, String filename) async {
    final directory = await getApplicationDocumentsDirectory();
    final filePath = '${directory.path}/audio/$filename';

    // 创建音频目录（如果不存在）
    final audioDir = Directory('${directory.path}/audio');
    if (!await audioDir.exists()) {
      await audioDir.create(recursive: true);
    }

    // 检查文件是否已存在
    final file = File(filePath);
    if (await file.exists()) {
      return filePath;
    }

    try {
      // 下载文件
      final httpClient = HttpClient();
      final request = await httpClient.getUrl(Uri.parse(url));
      final response = await request.close();

      if (response.statusCode == 200) {
        final bytes = await consolidateHttpClientResponseBytes(response);
        await file.writeAsBytes(bytes);
        return filePath;
      } else {
        final errorMessage = '下载音频文件失败: HTTP状态码 ${response.statusCode}';
        _errorStreamController.add(errorMessage);
        if (onError != null) {
          onError!(errorMessage);
        }
        throw Exception(errorMessage);
      }
    } catch (e) {
      final errorMessage = '下载音频文件失败: $e';
      _errorStreamController.add(errorMessage);
      if (onError != null) {
        onError!(errorMessage);
      }
      throw Exception(errorMessage);
    }
  }

  /// 重置播放器到初始状态
  /// Reset the player to its initial state
  Future<void> reset() async {
    if (!_initialized) return;
    await _player.stop();
    await _player.seek(Duration.zero);
    await _player.setVolume(1.0);
    await _player.setSpeed(1.0);
    await setPitch(1.0);  // 重置音调

    // 清除当前音频信息
    _currentAudio = null;
    _audioInfoStreamController.add(null);

    // 重置播放状态
    _updatePlaybackState(
      state: PlaybackState.uninitialized,
      audioInfo: null,
      error: null,
      position: Duration.zero,
      duration: Duration.zero,
    );

    // 重置回调
    onDurationChanged = null;
    onPositionChanged = null;
    onError = null;
    onCompleted = null;
    onAudioChanged = null;
    onPlaybackStateChanged = null;
  }


  /// 设置音调（0.5到2.0）
  /// Set the pitch (0.5 to 2.0)
  Future<void> setPitch(double pitch) async {
    if (!_initialized) return;
    _pitch = pitch.clamp(-3.0, 3.0);

    // 如果当前有音频在播放，重新加载音频以应用新的音调
    if (_currentAudio != null) {
      final currentPosition = _player.position;
      final wasPlaying = _player.playing;

      // 重新加载当前音频
      await loadAudio(
        _currentAudio!.source,
        title: _currentAudio!.title,
        artist: _currentAudio!.artist,
        album: _currentAudio!.album,
        artworkUrl: _currentAudio!.artworkUrl,
        extras: _currentAudio!.extras,
      );

      // 恢复播放位置
      await seek(currentPosition);

      // 如果之前在播放，则继续播放
      if (wasPlaying) {
        await play();
      }
    }
  }


  /// 释放资源
  /// Release resources when done
  Future<void> dispose() async {
    if (!_initialized) return;

    await _player.stop();
    await _player.dispose();

    _playingStreamController.close();
    _progressStreamController.close();
    _totalDurationStreamController.close();
    _bufferingStreamController.close();
    _errorStreamController.close();
    _audioInfoStreamController.close();
    _playbackStateStreamController.close();

    // 清除当前音频信息
    _currentAudio = null;

    // 清除回调
    onDurationChanged = null;
    onPositionChanged = null;
    onError = null;
    onCompleted = null;
    onAudioChanged = null;
    onPlaybackStateChanged = null;

    _initialized = false;
  }
}
